/**
 * 节流函数包装器 - 指定时间间隔内最多执行一次; 连续的多次调用仅第一次执行, 其余丢弃;
 * @param fn 需要节流的函数
 * @param msTime 防抖延迟, 单位毫秒; msTime 时间段内 能且只能执行一次
 * @returns 包装后的节流函数
 */
export function throttling<T extends (...args: any[]) => any>(fn: T, msTime: number): T {
    let lastExecutionTime: number | null = null

    return function (...args: any[]) {
        const now = Date.now()
        if (now - (lastExecutionTime ?? 0) <= msTime) {
            return null
        }
        lastExecutionTime = now
        return fn(...args)
    } as T
}

/**
 * 防抖函数包装器
 * - 连续的重复调用, 仅执行最后一次;
 * - 如果多次调用的时间间隔一直小于 timeInterval 此调用将一直等待.
 * <p style="color: red">因为最终函数需要包裹一层 setTimeout, 所以包装之后的函数会丢失返回值</p>
 * @param fn 需要防抖的函数
 * @param timeInterval 判定重复的时间间隔, 单位毫秒; 两次调用间隔时间小于 timeInterval 视为重复
 * @returns 包装后的防抖函数
 */
export function debounce<T extends (...args: any[]) => any>(fn: T, timeInterval: number): T {
    let timer: any = null

    return function (...args: any[]) {
        if (timer != null) {
            window.clearTimeout(timer)
        }
        timer = window.setTimeout(() => {
            fn(...args)
            timer = null
        }, timeInterval)
    } as T
}
